package io.atomix.copycat.client.util;
import org.testng.annotations.Test;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
/**
* Ordered completable future test.
*/
@Test
public class OrderedCompletableFutureTest {
/**
* Tests ordered completion of future callbacks.
*/
public void testOrderedCompletion() throws Throwable {
CompletableFuture<String> future = new OrderedCompletableFuture<>();
AtomicInteger order = new AtomicInteger();
future.whenComplete((r, e) -> assertEquals(1, order.incrementAndGet()));
future.whenComplete((r, e) -> assertEquals(2, order.incrementAndGet()));
future.handle((r, e) -> {
assertEquals(3, order.incrementAndGet());
assertEquals(r, "foo");
return "bar";
});
future.thenRun(() -> assertEquals(3, order.incrementAndGet()));
future.thenAccept(r -> {
assertEquals(5, order.incrementAndGet());
assertEquals(r, "foo");
});
future.thenApply(r -> {
assertEquals(6, order.incrementAndGet());
assertEquals(r, "foo");
return "bar";
});
future.whenComplete((r, e) -> {
assertEquals(7, order.incrementAndGet());
assertEquals(r, "foo");
});
future.complete("foo");
}
/**
* Tests ordered failure of future callbacks.
*/
public void testOrderedFailure() throws Throwable {
CompletableFuture<String> future = new OrderedCompletableFuture<>();
AtomicInteger order = new AtomicInteger();
future.whenComplete((r, e) -> assertEquals(1, order.incrementAndGet()));
future.whenComplete((r, e) -> assertEquals(2, order.incrementAndGet()));
future.handle((r, e) -> {
assertEquals(3, order.incrementAndGet());
return "bar";
});
future.thenRun(() -> fail());
future.thenAccept(r -> fail());
future.exceptionally(e -> {
assertEquals(3, order.incrementAndGet());
return "bar";
});
future.completeExceptionally(new RuntimeException("foo"));
}
/**
* Tests calling callbacks that are added after completion.
*/
public void testAfterComplete() throws Throwable {
CompletableFuture<String> future = new OrderedCompletableFuture<>();
future.whenComplete((result, error) -> assertEquals(result, "foo"));
future.complete("foo");
AtomicInteger count = new AtomicInteger();
future.whenComplete((result, error) -> {
assertEquals(result, "foo");
assertEquals(count.incrementAndGet(), 1);
});
future.thenAccept(result -> {
assertEquals(result, "foo");
assertEquals(count.incrementAndGet(), 2);
});
assertEquals(count.get(), 2);
}
}